-
Notifications
You must be signed in to change notification settings - Fork 769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stm32 i2c slave #2909
base: main
Are you sure you want to change the base?
stm32 i2c slave #2909
Conversation
Hi Jared, interesting. Will respond soon if I figure anything out. |
I've figured out why the function wasn't being polled. Now just working on finishing up the implementation |
@Dirbaio the stm32 i2c supports multimaster for allowing both a master and a slave functionality. The slave mode is the default and the master mode is enabled by a start condition and ends with a stop condition. Currently in this implementation I have split the slave from the master. This more closely matches the API in the embassy-rp crate. Would it be better to join them and merge the slave functionality into the regular i2c driver (in order to let you switch from slave to master without reconfiguring) or is it better to leave them split? (edited) |
I think being part of the regular driver works, if say you introduce a Thoughts? |
@jrmoulton see CI issues please, just a heads up. keen to test this soon - thanks so much!! edit: did some tracing to help you with picking this up mate - these seem CI related only, as your build works |
@Dirbaio I like your CI page title "lol job"?? https://ci.embassy.dev/jobs/586c0e7a5b13 |
test result: ok. 3 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 0.06s
Updating crates.io index
Updating git repository `https://github.com/embassy-rs/stm32-data-generated`
Compiling embassy-hal-internal v0.1.0 (/ci/code/embassy-hal-internal)
Compiling embassy-time v0.3.0 (/ci/code/embassy-time)
Compiling embassy-usb-synopsys-otg v0.1.0 (/ci/code/embassy-usb-synopsys-otg)
Compiling embassy-stm32 v0.1.0 (/ci/code/embassy-stm32)
Compiling embassy-net-driver v0.2.0 (/ci/code/embassy-net-driver)
Compiling embassy-embedded-hal v0.1.0 (/ci/code/embassy-embedded-hal)
error[E0432]: unresolved import `stm32_metapac::i2c::vals::Oamsk`
--> src/i2c/mod.rs:19:5
|
19 | use stm32_metapac::i2c::vals::Oamsk;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `Oamsk` in `i2c::vals`
warning: unused import: `interrupt`
--> src/time_driver.rs:19:13
|
19 | use crate::{interrupt, peripherals};
| ^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unused import: `interrupt`
--> src/exti.rs:14:13
|
14 | use crate::{interrupt, pac, peripherals, Peripheral};
| ^^^^^^^^^
error[E0599]: no method named `init` found for struct `I2cSlave` in the current scope
--> src/i2c/mod.rs:367:14
|
299 | pub struct I2cSlave<'d, T: Instance, M: Mode> {
| --------------------------------------------- method `init` not found for this struct
...
367 | this.init(freq, config);
| ^^^^ method not found in `I2cSlave<'_, T, M>`
warning: unused variable: `waker`
--> src/dma/ringbuffer.rs:429:33
|
429 | fn set_waker(&mut self, waker: &Waker) {}
| ^^^^^ help: if this is intentional, prefix it with an underscore: `_waker`
|
= note: `#[warn(unused_variables)]` on by default |
embassy-stm32/src/i2c/mod.rs
Outdated
_phantom: PhantomData, | ||
}; | ||
|
||
this.init(freq, config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing.
embassy-stm32/src/i2c/mod.rs
Outdated
@@ -13,6 +16,7 @@ use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; | |||
use embassy_sync::waitqueue::AtomicWaker; | |||
#[cfg(feature = "time")] | |||
use embassy_time::{Duration, Instant}; | |||
use stm32_metapac::i2c::vals::Oamsk; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Odd error in CI, needs a deeper look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't been able to figure out why I am getting this error in CI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be @Dirbaio can help, he's very familiar with his CI setup. I'm curious too.
I'm in the process of reworking the I2C driver to be generic over an I2C mode which can either be Master, Slave, or MultiMaster. |
Just wanted to let you know that I'm also eagerly awaiting slave mode, thanks a lot @jrmoulton! |
796b5c0
to
b3dcfd4
Compare
The last remaining ci issues are unrelated to this PR. Finally actually ready for review |
@Dirbaio is there anything else I need to do in order for this PR to be reviewed? |
yes, make CI pass. Once CI is green it'll be reviewed |
4da9bd1
to
daeefdd
Compare
any updates on this? |
I need to undo a few changes that I made and then the CI should pass. It's close. I just haven't spent the last hour or two to get it finished. |
seems like now there are 2 pull requests for I2C slave on stm32. yesterday I tried to use I2C on stm32 and was confused which one to use. |
daeefdd
to
b4eb4a3
Compare
27d70a0
to
5061963
Compare
Can you please provide an example of using i2c slave for any stm32 mcu? @jrmoulton |
I'll add one |
I haven't actually tested the example that I've added. I've tested the slave code but not in this particular example. I've made this example match as closely as I could to the rp2040 i2c slave example. |
Thanks! I'll test the example with STM32L071CB tomorrow |
@Dirbaio can this be reviewed? It seem to look ready |
@okhsunrog it looks like the esp32c3 doesn't support clock stretching. When you say you are increasing the timeout, do you mean on the esp32c3 master or on the stm32 slave? |
@jrmoulton it turned out that even the maximum timeout for SCL pin stretching wasn't enough, so I just patched esp-idf code to set I2C_TIME_OUT_EN bit to 0 manually, and now it doesn't time out. Otherwise I2C_TIME_OUT_INT interrupt is triggered. Now the code doesn't exit with timeout, esp32-c3 waits patiently for stm32 to answer. I'm just using i2c-tools from esp-idf examples for testing, with timeouts disabled by patching one line in esp-idf (they hardcoded setting this bit to 1).
on stm32 side I see strange timeouts:
And the I2C line stretching is really long for i2cget. For writing data, the SCL line is pulled only for about 270-280 us. When I do i2cget, the stretching for writing byte with "register address" is the same, about 280us, but for reading a byte of data, the stretching is really long! It's almost a second, 946ms. You can see on the screenshots below. I found this in your code:
Maybe it's somehow related for the SCL line getting stretched for a whole second? And what exactly that timeout it about? |
That timeout is used for the slave as a maximum time to wait for the master when doing a read or write. It isn't directly related. The reason that the clock is being stretched for so long is that, the way it is written, the executor has to schedule the task that will respond to the request from the master. This code does not immediately start responding. There are reasons that I wrote it this way. The biggest is that in order to respond immediately, the slave needs to have a buffer ready which doesn't really work if the slave can match multiple addresses. Some logic based on the matched address is necessary. I tried to find a way to store a closure to handle this logic but without an allocator I couldn't find a way to do it. So instead the clock is stretched until the task is scheduled and the user decides how to respond once they have seen the matched address. It would probably be useful to have functions that work without clock stretching but I haven't written those (Edit) |
Yes, one second is very long. And what about |
Not sure. There could be several reasons. Hard to say without seeing all of the code that you are using |
I'll send the full code tomorrow. I just got Discovery F4 board, I'll test it both as slave and as master and post the results here too |
That's the code I used for slave: https://github.com/okhsunrog/stm32l071_i2c_slave_test |
@jrmoulton yesterday I had some free time and I investigated into this issue some more time. The stretching of SCL for 1 second seems to be because of this:
I tried different timeouts manually and the scl is indeed stretched for the duration I set. When I set it to |
@jrmoulton you're doing |
Did you test both blocking and async? |
Can you share your memory.x as well please? |
This isn't quite finished. It only has the async slave implementation and the code needs to be cleaned up.
I could use some help debugging also.
In the listen method I enable the address match interrupt and register the waker in the poll closure.
The issue is that the runtime never polls the function again even when an address is matched.
If I write code that blocks instead of yielding and send and I2C communication the peripheral will still be enabled and will match the address.
I've tried also adding the wupen bit but that didn't make a difference
Any idea why the runtime wouldn't poll the function again?